package com.youngjun.common.mybatis.plugin;

import com.youngjun.common.mybatis.autoconfigure.MybatisHelperProperties;
import com.youngjun.common.util.IdWorker;
import com.youngjun.common.util.SpringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.util.List;
import java.util.Properties;

/**
 * @author VirgoJun
 */
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class MybatisHelper implements Interceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(MybatisHelper.class);

    private MybatisHelperProperties properties;

    public MybatisHelper(MybatisHelperProperties properties){
        this.properties=properties;
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();

        boolean flag = false;
        Object parameterObject = args[1];
        if(SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)){
            if (parameterObject instanceof List) {
                return invocation.proceed();
            }
            flag=true;
        }

        if(flag){
            MetaObject parameterMetaObject = SystemMetaObject.forObject(parameterObject);
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            //设置属性值
            parameterMetaObject.setValue(properties.getModifiedTimeKey(), timestamp);
            //使用分布式id
            if(SqlCommandType.INSERT.equals(sqlCommandType)){
                parameterMetaObject.setValue(properties.getCreatedTimeKey(), timestamp);
                Object primaryKeyValue = parameterMetaObject.getValue(properties.getPrimaryKey());
                if (primaryKeyValue == null) {
                    long id = SpringUtils.getBean(IdWorker.class).nextId();
                    parameterMetaObject.setValue(properties.getPrimaryKey(), id);
                }
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if(target instanceof Executor){
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {}
}
